package bert;

import java.io.IOException;
import java.io.InputStream;

import org.xml.sax.helpers.DefaultHandler;
import java.util.ArrayList;
import java.util.HashMap;

import javax.xml.parsers.ParserConfigurationException;

import org.xml.sax.SAXException;
import org.xml.sax.Attributes;

import javax.xml.parsers.SAXParser;

import javax.xml.parsers.SAXParserFactory;


public class SvgLoader
{
	public static RawTrackGeometry ReadStream(InputStream data) 
	{
		try
		{
			SAXParserFactory parserFactory = SAXParserFactory.newInstance();
			SAXParser parser = parserFactory.newSAXParser();
		
			final ArrayList<Polygon> polygons = new ArrayList<Polygon>();
			final HashMap<String, Polygon> endpoints = new HashMap<String, Polygon>();
			
			parser.parse(data, new DefaultHandler()
			{
				@Override
				public void startElement(String uri, String localName, String qName, Attributes attributes)
				{
					if(qName.equals("path"))
					{
						StringBuilder sb = new StringBuilder(attributes.getValue("d"));
						
						boolean relativeCoords = sb.charAt(0) == 'm';
						
						while (sb.length() > 0 && !Character.isDigit(sb.charAt(0))) {
                            sb.deleteCharAt(0);
                        }
						
						assert sb.length() > 0;
						
						while (sb.length() > 0 && !Character.isDigit(sb.charAt(sb.length()-1))) {
                            sb.deleteCharAt(sb.length()-1);
                        }
						
						String[] points = sb.toString().split("\\s");
						
						ArrayList<Vec2> vertices = new ArrayList<Vec2>();
						
						for (String point : points) 
						{
							String[] coords = point.split(",");
							assert coords.length == 2;
							
							int x = (int)Math.round(Double.parseDouble(coords[0]));
							int y = (int)Math.round(Double.parseDouble(coords[1]));
							
							if (relativeCoords && vertices.size() > 0)
							{
								Vec2 prevVertex = vertices.get(vertices.size()-1);
								Vec2 newVertex = new Vec2(x,y).add(prevVertex);
								vertices.add(newVertex);
							}
							else
							{
								vertices.add(new Vec2(x, y));
							}
						}
												
						final Polygon polygon = new Polygon(vertices.toArray(new Vec2[vertices.size()]), polygons.size());
						polygons.add(polygon);
						
						if (attributes.getValue("id").equals("first") 
						 || attributes.getValue("id").equals("last")) {
                            endpoints.put(attributes.getValue("id"), polygon);
                        }
					}
				}
			});
			
			assert (endpoints.containsKey("first"));
			assert (endpoints.containsKey("last"));
			
			return new RawTrackGeometry(polygons, endpoints.get("first"), endpoints.get("last"));
		}
		catch(IOException e)
		{
			
		}
		catch(ParserConfigurationException e)
		{
			
		}
		catch(SAXException e)
		{
						
		}
		
		throw new RuntimeException();
	}
}
